<template>
  <a-modal :title="title" :width="800" :visible="visible" :confirmLoading="confirmLoading" @ok="handleOk"  @cancel="handleCancel" cancelText="关闭">
    <a-spin :spinning="confirmLoading">
      <a-form :form="form">
        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="数据源名称">
          <a-input placeholder="请输入数据源名称" v-decorator="['name', validatorRules.name]" autocomplete="off" :disabled="disableSubmit" />
        </a-form-item>
        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="数据库类型">
          <j-dict-select-tag placeholder="请选择数据库类型" dict-code="database_type" triggerChange v-decorator="['dbType', validatorRules.dbType]" @change="handleDbTypeChange" :disabled="disableSubmit" />
        </a-form-item>
        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="驱动类" v-show="databaseType != '5'">
          <a-input autocomplete="off"  placeholder="请输入驱动类" v-decorator="['dbDriver', databaseType != '5' ? validatorRules.dbDriver : {}]" :disabled="disableSubmit" />
        </a-form-item>
        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="数据源地址">
          <a-input autocomplete="off"  placeholder="请输入数据源地址" v-decorator="['dbUrl', validatorRules.dbUrl]" :disabled="disableSubmit" />
        </a-form-item>
        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="数据库名称" v-show="databaseType != '5'">
          <a-input autocomplete="off" placeholder="请输入数据库名称" v-decorator="['dbName', databaseType != '5' ? validatorRules.dbName : {}]" :disabled="disableSubmit" />
        </a-form-item>
        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="数据库名称" v-show="databaseType == '5'">
          <a-row :gutter="8">
            <a-col :span="21">
              <a-input autocomplete="off" placeholder="请输入数据库名称" v-decorator="['dbName', databaseType == '5' ? validatorRules.dbName : {}]" :disabled="disableSubmit" />
            </a-col>
            <a-col :span="3">
              <a-button class="atn-testbtn" type="primary" size="small" style="width: 100%" @click="handleTest">测试</a-button>
            </a-col>
          </a-row>
        </a-form-item>

        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="用户名" v-show="databaseType != '5'">
          <a-input autocomplete="off" placeholder="请输入用户名" v-decorator="['dbUsername', databaseType != '5' ? validatorRules.dbUsername : {}]"  :disabled="disableSubmit" />
        </a-form-item>

        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="密码" v-show="databaseType != '5'">
          <a-row :gutter="8">
            <a-col :span="21">
              <a-input-password autocomplete="off" placeholder="请输入密码" v-decorator="['dbPassword',  databaseType != '5' ? validatorRules.dbPassword : {}]" :disabled="disableSubmit" />
            </a-col>
            <a-col :span="3">
              <a-button class="atn-testbtn" type="primary" size="small" style="width: 100%" @click="handleTest">测试</a-button>
            </a-col>
          </a-row>
        </a-form-item>

        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="备注">
          <a-textarea placeholder="请输入备注" v-decorator="['remark', {}]" :disabled="disableSubmit" :rows="4" />
        </a-form-item>
        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="状态">
          <a-radio-group :disabled="disableSubmit" v-decorator="['dbStatus', { initialValue: '1', rules: [{required: true}] }]">
            <a-radio value="1">启用</a-radio>
            <a-radio value="0">停用</a-radio>
          </a-radio-group>
        </a-form-item>
      </a-form>
    </a-spin>
  </a-modal>
</template>

<script>
import pick from 'lodash.pick'
import { randomUUID } from '@/utils/util'
import { formatInput } from '@/utils/fix'
import { httpAction, postAction, getAction } from '@/api/manage'

export default {
  name: 'SysDataSourceModal',
  components: {},
  data() {
    return {
      databaseType: null,
      title: '操作',
      visible: false,
      disableSubmit: false,
      dataSourceList: [],
      model: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      confirmLoading: false,
      form: this.$form.createForm(this),
      validatorRules: {
        name: { rules: [{ required: true, message: '请输入数据源名称!' }] },
        dbType: { rules: [{ required: true, message: '请选择数据库类型!' }] },
        dbDriver: { rules: [{ required: true, message: '请输入驱动类!' }] },
        dbUrl: { rules: [{ required: true, message: '请输入数据源地址!' }] },
        dbName: { rules: [{ required: true, message: '请输入数据库名称!' }] },
        dbUsername: { rules: [{ required: true, message: '请输入用户名!' }] },
        dbPassword: { rules: [{ required: true, message: '请输入密码!' }] }
      },
      url: {
        add: '/sys/dataSource/add',
        edit: '/sys/dataSource/edit'
      },
      dbDriverMap: {
        // MySQL 数据库
        '1': { dbDriver: 'com.mysql.jdbc.Driver' },
        // MySQL5.7+ 数据库
        '4': { dbDriver: 'com.mysql.cj.jdbc.Driver' },
        // Oracle
        '2': { dbDriver: 'oracle.jdbc.OracleDriver' },
        // SQLServer 数据库
        '3': { dbDriver: 'com.microsoft.sqlserver.jdbc.SQLServerDriver' }
      },
      dbUrlMap: {
        // MySQL 数据库
        '1': { dbUrl: 'jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false' },
        // MySQL5.7+ 数据库
        '4': { dbUrl: 'jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai' },
        // Oracle
        '2': { dbUrl: 'jdbc:oracle:thin:@127.0.0.1:1521:ORCL' },
        // SQLServer 数据库
        '3': { dbUrl: 'jdbc:sqlserver://127.0.0.1:1433;SelectMethod=cursor;DatabaseName=jeecgboot' }
      },
      identity: '1'
    }
  },
  created() {
    this.getDataSourceList()
  },
  methods: {
    formatInput,
    add() {
      this.edit({})
    },
    edit(record) {
      this.form.resetFields()
      this.model = Object.assign({}, record)
      this.visible = true
      this.$nextTick(() => {
        this.databaseType = this.model.dbType
        this.form.setFieldsValue(pick(this.model, 'name', 'remark', 'dbType', 'dbDriver', 'dbUrl', 'dbName', 'dbUsername', 'dbPassword', 'dbStatus'))
      })
    },
    close() {
      this.databaseType = null
      this.$emit('close')
      this.visible = false
      this.disableSubmit = false
    },
    getDataSourceList() {
      getAction('/sys/dataSource/list', { pageNo: 1, pageSize: 10000 }).then((res) => {
        if (res.success) {
          this.dataSourceList = res.result.records
        } else {
          this.dataSourceList = []
        }
      })
    },
    handleOk() {
      // 触发表单验证
      this.form.validateFields((err, values) => {
        if (!err) {
          this.confirmLoading = true
          const formData = Object.assign(this.model, values)
          let httpUrl = this.url.add
          let method = 'post'
          formData['code'] = randomUUID()
          if (this.model.id) {
            httpUrl = this.url.edit
            method = 'put'
            // 由于编码的特殊性，所以不能更改
            formData['code'] = undefined
          }
          httpAction(httpUrl, formData, method).then((res) => {
            if (res.success) {
              this.$message.success(res.message)
              this.$emit('ok')
              this.close()
            } else {
              this.$message.warning(res.message)
            }
          }).finally(() => {
            this.confirmLoading = false
          })
        }
      })
    },
    handleCancel() {
      this.close()
    },
    // 测试数据源配置是否可以正常连接
    handleTest() {
      const keys = ['dbType', 'dbDriver', 'dbUrl', 'dbName', 'dbUsername', 'dbPassword']
      // 获取以上字段的值，并清除校验状态
      const fieldsValues = this.form.getFieldsValue(keys)
      const setFields = {}
      keys.forEach(key => { setFields[key] = { value: fieldsValues[key], errors: null } })
      // 清除校验状态，目的是可以让错误文字闪烁
      this.form.setFields(setFields)
      // 重新校验
      this.$nextTick(() => {
        this.form.validateFields(keys, (errors, values) => {
          if (!errors) {
            const loading = this.$message.loading('连接中……', 0)
            postAction('/stuationDataSource/testConnection', fieldsValues).then(res => {
              if (res.success) {
                this.$message.success('连接成功')
              } else throw new Error(res.message)
            }).catch(error => {
              this.$warning({ title: '连接失败', content: error.message || error })
            }).finally(() => loading())
          }
        })
      })
    },
    // 数据库类型更改时，联动更改数据库驱动
    handleDbTypeChange(val) {
      this.databaseType = val
      if (val == '5') {
        this.form.setFieldsValue({ dbDriver: null })
        this.form.setFieldsValue({ dbUrl: null })
      } else {
        this.$nextTick(() => {
          const dbDriver = this.dbDriverMap[val]
          const dbUrl = this.dbUrlMap[val]
          if (dbDriver) {
            this.form.setFieldsValue(dbDriver)
          }
          if (dbUrl) {
            this.form.setFieldsValue(dbUrl)
          }
        })
      }
    }
  }
}
</script>

<style lang="less" scoped>
.atn-testbtn {
    color: #2F77F2 !important;
    background: #FFFFFF !important;
    box-shadow: 0px 1px 3px 0px rgba(4, 0, 0, 0.08) !important;
    border: 1px solid #2F77F2 !important;
    border-radius: 2px !important;
    padding: 0 10px !important;
    height: 34px !important;
    margin: 0 8px 8px 0;
}
</style>
